<template>
  <!-- 不考虑分页 -->
  <el-select
    ref="zmSelect"
    v-model="selectValue"
    v-bind="$attrs"
    v-on="$listeners"
    :filterable="selectOpt.filterable"
    :filter-method="remoteMethod"
    :remote="selectOpt.remote"
    :remote-method="remoteMethod"
    :multiple="selectOpt.multiple"
    :reserve-keyword="selectOpt.multiple"
    :disabled="selectOpt.disabled"
    @visible-change="visibleChange"
    @focus="getFocus"
    @clear="clearSelect"
    @remove-tag="removeTag "
    clearable
  >
    <el-option
      :label="item[apiParams.name]"
      :value="item[apiParams.id]"
      v-for="(item,index) in optionsData"
      :key="index"
      @click.native="chooseId(item)"
    ></el-option>
    <!-- <i slot="suffix" class="el-icon-loading" v-show="selectLoading"></i> -->
    <!-- ！！封装el-select如果出现宽体高度变窄，都要看下是否是disabled的原因 -->
  </el-select>
</template>
<script>
import { apiType } from './const'
export default {
  props: {
    value: {
      type: [String, Array, Number],
      default: ''
    },
    // 传入的api类型
    selectType: {
      type: String,
      default: ''
    },
    // 传入的设置参数
    attrOption: {
      type: Object,
      default () {
        return {
          multiple: false,
          isAll: false // 是否有全部选项
        }
      }
    },
    // 传入的额外查询参数
    actionQuery: {
      type: Object,
      default () {
        return {}
      }
    },
    // 刷新可选列表
    reloadOption: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      apiType,
      selectValue: '',
      selectLoading: false,
      isBackfill: false,
      selectOpt: {
        isStringIds: true, // 是否获取字符串id集合
        multiple: false, // 是否多选
        filterable: true, // 是否可搜索
        remote: false, // 是否远程搜素
        disabled: false, // 是否禁用选项
        showNum: 0 // 显示选项数，默认0（展示所有）
      },
      apiParams: {
        // 组件接口参数
        name: '',
        id: '',
        api: ''
      },
      optionsData: [], // 展示用选项数组
      list: [], // 完整选项数组
      queryParams: {} // 默认查询参数
    }
  },
  computed: {
    apiJs () {
      // 根据传入类型引入api文件
      const apiParams = this.apiType[this.selectType] || {}
      return () => import(`@/api/src/${apiParams.js}.js`)
    }
  },
  watch: {
    value (val) {
      if (!val || +val === -1) this.$emit('visible-false-change')
      const oldVal =
        val && this.selectOpt.multiple && typeof val === 'string'
          ? val.split(',').filter(e => e)
          : val
      const oldValToArr = [].concat(oldVal)
      const newValToArr = [].concat(this.selectValue)
      if (JSON.stringify(oldValToArr) !== JSON.stringify(newValToArr)) {
        this.getInfo(oldVal)
      }
    },
    async reloadOption (val, oldVal) {
      if (val) {
        await this.getOptionArr()
        // 需要内部还原值，外部属性添加修饰符sync即可，不设置则外部做还原控制
        this.$emit('update:reloadOption', false)
      }
    },
    selectType (val, oldVal) {
      if (val) this.getApiType()
    }
  },
  mounted () {
    // 传入的selectOpt覆盖默认设置
    this.selectOpt = Object.assign({}, this.selectOpt, this.attrOption)
    this.selectValue = this.attrOption.multiple ? [] : ''
    this.getApiType()
    // 组件被重复创建但是value值没有变化时
    if (this.value && this.value.length) this.getInfo(this.value)
  },
  methods: {
    // 清除时
    clearSelect () {
      this.selectValue = this.selectOpt.multiple ? [] : ''
      this.changeSelect(this.selectValue)
    },
    removeTag () {
      this.changeSelect(this.selectValue)
      this.$emit('visible-false-change')
    },
    // 获取全部选项
    getAllSelect () {
      // 根据name和id值扩展全部选项
      const SELECTION_ALL = {}
      SELECTION_ALL[this.apiParams.name] = '全部'
      SELECTION_ALL[this.apiParams.id] = '-1'
      if (this.selectOpt.isAll) {
        if (
          !this.list.length ||
          (this.list &&
            this.list.length &&
            +this.list[0][this.apiParams.id] !== -1)
        ) {
          this.list.unshift(SELECTION_ALL)
        }
      }
      this.optionsData = this.list
    },
    // 回填数据
    async getInfo (val) {
      // 回填时，判断下是否是表单回填，如果是-1的回填且焦点后触发接口，则赋-1的初始选项值
      const listLen = this.attrOption.isAll ? 1 : 0
      if (+val !== -1 && this.list.length === listLen) {
        await this.getOptionArr()
      } else {
        this.getAllSelect()
      }
      // 不考虑分页做回填，数据请求完毕后再进行回填
      if (JSON.stringify(val) !== JSON.stringify(this.selectValue)) {
        if (this.selectOpt.multiple) {
          this.selectValue = val
            ? Array.isArray(val)
              ? val
              : val.split(',').filter(e => e)
            : []
        } else {
          this.selectValue = val + '' || ''
        }
        this.changeSelect(this.selectValue, true)
      }
    },
    // 根据外部传入的类型获取api参数
    async getApiType () {
      const apiParams = this.apiType[this.selectType]
      this.$set(this.apiParams, 'name', apiParams.name || 'name')
      this.$set(this.apiParams, 'id', apiParams.id || 'value')
      this.$set(this.apiParams, 'api', apiParams.selectApi)
    },
    // 通过接口获取选项数组
    getOptionArr () {
      // const this = this
      return new Promise((resolve, reject) => {
        // this.selectLoading = true
        // 链接内部参数和外部参数
        this.queryParams = Object.assign({}, this.queryParams, this.actionQuery)
        this.apiParams
          .api(this.queryParams)
          .then(res => {
            const data = JSON.parse(JSON.stringify(res.data || res))
            data &&
              data.length &&
              data.forEach(e => {
                e[this.apiParams.id] = e[this.apiParams.id] + ''
              })
            this.selectLoading = false
            if (!this.selectOpt.showNum) {
              this.optionsData = data
              this.list = data
            } else {
              const optionTemp = data
              this.optionsData = optionTemp.slice(0, this.selectOpt.showNum)
              this.list = optionTemp.slice(0, this.selectOpt.showNum)
            }
            this.getAllSelect()
            resolve()
          })
          .catch(error => {
            this.selectLoading = false
            reject(error)
          })
      })
    },
    remoteMethod (remoteVal) {
      if (remoteVal) {
        setTimeout(() => {
          this.optionsData = this.list.filter((item, index) => {
            for (var key in item) {
              if (key === this.apiParams.name) {
                const itemKey = item[key] || ''
                return itemKey.indexOf(remoteVal) > -1
              }
            }
          })
        }, 200)
      } else {
        this.optionsData = this.list
      }
    },
    getFocus (val) {
      if (+this.selectValue === -1) val.target.value = ''
      // 多选时处理值被清空时，拉回所有列表
      if (!val.target.value && this.attrOption.multiple) this.remoteMethod('')
    },
    // 点击
    chooseId (item) {
      // 多选操作，需要选择全部时,处理下选项关系
      if (this.attrOption.multiple && this.attrOption.isAll) {
        if (+item[this.apiParams.id] === -1) {
          this.selectValue.splice(0)
          this.selectValue.push('-1')
        } else {
          const index = this.selectValue.findIndex(e => {
            return +e === -1
          })
          if (index !== -1) this.selectValue.splice(index, 1)
        }
      }
      this.changeSelect(this.selectValue)
    },
    changeSelect (val, Boolean) {
      if (!Boolean) {
        this.$emit(
          'input',
          this.selectOpt.multiple && this.selectOpt.isStringIds
            ? val.filter(i => i).join(',')
            : val
        )
      }
      // 筛选选中的值以数组形式传出，单选的情况下则为单项数组
      const chooseArr = []
      this.list.forEach(e => {
        if (this.attrOption.multiple) {
          val.forEach(item => {
            if (item === e[this.apiParams.id]) {
              chooseArr.push(e)
            }
          })
        } else {
          if (e[this.apiParams.id] === val) chooseArr.push(e)
        }
      })
      this.$emit('change-select', chooseArr)
    },
    visibleChange (val) {
      if (val) {
        // 不需要回填的时候，手动加载数据,展开时如果没有可选数组则获取数据
        const isRequest = this.selectOpt.isAll
          ? this.optionsData.length === 1
          : !this.optionsData.length
        if (isRequest) {
          this.getOptionArr()
        }
        // 单选时处理值被清空时，拉回所有列表
        if (
          !(this.selectValue && this.selectValue.length) &&
          !this.selectOpt.multiple
        ) {
          this.remoteMethod('')
        }
      } else {
        // 收缩时，更新外部数据
        this.changeSelect(this.selectValue)
        this.$emit('visible-false-change')
      }
    }
  }
}
</script>
